package com.perfect.service;

import com.perfect.base.BaseService;
import com.perfect.dao.ModuleMapper;
import com.perfect.dao.PermissionMapper;
import com.perfect.dao.RoleMapper;
import com.perfect.utils.AssertUtil;
import com.perfect.vo.Permission;
import com.perfect.vo.Role;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


@Service
public class RoleService extends BaseService<Role, Integer> {

    @Resource
    private RoleMapper roleMapper;
    @Resource
    private ModuleMapper moduleMapper;
    @Resource
    PermissionMapper permissionMapper;

    /**
     * 添加角色
     * 1. 参数校验
     * 角色名称        非空，名称唯一
     * 2. 设置参数的默认值
     * 是否有效
     * 创建时间
     * 修改时间
     * 3. 执行添加操作，判断受影响的行数
     *
     * @param role 角色相关信息
     * @return void
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void saveRole(Role role) {

        // 验证角色名是否为空
        AssertUtil.isTrue(StringUtils.isBlank(role.getRoleName()), "角色名不能为空");
        // 验证角色名唯一性
        AssertUtil.isTrue(null != roleMapper.selectByParams(role.getRoleName()), "该角色已存在");

        // 设置参数默认值
        role.setIsValid(1);
        role.setCreateDate(new Date());
        role.setUpdateDate(new Date());

        //执行添加操作
        AssertUtil.isTrue(roleMapper.insertSelective(role) < 1, "角色添加失败");
    }

    /**
     * 修改角色
     * 1. 参数校验
     * 角色ID    非空，且数据存在
     * 角色名称   非空，名称唯一
     * 2. 设置参数的默认值
     * 修改时间
     * 3. 执行更新操作，判断受影响的行数
     *
     * @param role 角色记录
     * @return void
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateRole(Role role) {

        // 验证id 是否为空
        AssertUtil.isTrue(null == role.getId(), "待更新记录不存在！");
        // 查询该角色记录是否存在
        AssertUtil.isTrue(null == roleMapper.selectByPrimaryKey(role.getId()), "待更新记录不存在！");
        // 验证角色名称 非空,唯一
        AssertUtil.isTrue(null == role.getRoleName(), "角色名不能为空");
        // 判断角色记录是否存在（如果不存在，表示可使用；如果存在，且角色ID与当前更新的角色ID不一致，表示角色名称不可用）
        Role temp = roleMapper.selectByParams(role.getRoleName());
        AssertUtil.isTrue(null != temp && !temp.getId().equals(role.getId()), "该角色名称已存在");

        // 设置参数默认值
        role.setUpdateDate(new Date());

        // 执行更新操作
        AssertUtil.isTrue(roleMapper.updateByPrimaryKeySelective(role) < 1, "操作失败");
    }

    /**
     * 删除角色记录
     *
     * @param roleId
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void delRole(Integer roleId) {

        Role temp = roleMapper.selectByPrimaryKey(roleId);
        // 验证角色Id是否为空, 根据角色Id验证角色记录是否存在
        AssertUtil.isTrue(null == roleId || null == temp, "待删除记录不存在");
        // 设置参数默认值
        temp.setIsValid(0);
        // 执行伪删除操作
        AssertUtil.isTrue(roleMapper.updateByPrimaryKeySelective(temp) < 1, "删除失败");
    }

    /**
     * 角色授权
     * <p>
     * 将对应的角色ID与资源ID，添加到对应的权限表中
     * 直接添加权限：不合适，会出现重复的权限数据（执行修改权限操作后删除权限操作时）
     * 推荐使用：
     * 先将已有的权限记录删除，再将需要设置的权限记录添加
     * 1. 通过角色ID查询对应的权限记录
     * 2. 如果权限记录存在，则删除对应的角色拥有的权限记录
     * 3. 如果有权限记录，则添加权限记录 (批量添加)
     *
     * @param roleId 角色ID
     * @param mIds   资源ID
     * @return void
     */
    public void grantRole(Integer roleId, Integer[] mIds) {
        // 根据角色ID查询该角色是否有资源记录
        Integer count = permissionMapper.countPermissionByRoleId(roleId);
        // 如果有,删除对应资源记录
        if (count > 0) {
            permissionMapper.deletePermissionByRoleId(roleId);
        }

        // 判断前端传过来的资源记录是否存在,如果存在,添加对应的资源记录
        if (null != mIds && mIds.length > 0) {
            // 定义Permission集合
            List<Permission> permissionList = new ArrayList<>();
            // 遍历资源ID数组
            for (Integer mId : mIds) {
                Permission permission = new Permission();
                permission.setModuleId(mId);
                permission.setRoleId(roleId);
                permission.setAclValue(moduleMapper.selectByPrimaryKey(mId).getOptValue());
                permission.setCreateDate(new Date());
                permission.setUpdateDate(new Date());
                // 将对象设置到集合中
                permissionList.add(permission);
            }
            // 执行批量添加操作
            AssertUtil.isTrue(permissionMapper.insertBatch(permissionList) != permissionList.size(), "资源添加失败!");
        }

    }
}
